/***************************************************************************
 创建者: 华磊
 开始时间: 2018.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2017.5.8 类的具体实现代码编写

 ***************************************************************************/
#include "modbusiomoduledriver.h"
#include "modbusiomoduleconfig.h"
#include <qdebug.h>

ModbusIoModuleDriver::ModbusIoModuleDriver(QString fileName, int modbusIdIn,
                             int *globalCurrentAliasIn, modbus_t *globalCurrentModbusMasterIn)
{
    isInitialedOk=false;
    modbusId=modbusIdIn;
    modbusMaster=NULL;
    globalCurrentAlias=globalCurrentAliasIn;
    globalCurrentModbusMaster=globalCurrentModbusMasterIn;
    initial(fileName);
}

ModbusIoModuleDriver::~ModbusIoModuleDriver()
{
}

int ModbusIoModuleDriver::initial(QString fileName)
{
    qDebug()<<"ModbusIoModuleDriver initial ,file name="<<fileName;
    ioModuleConfig=new ModbusIoModuleConfig(fileName);
    if(true==ioModuleConfig->isInitialOkStatus())
    {
        ioModuleConfig->getParameter(comParameter,regAdd,vendorId);
        ioModuleConfig->getDiDoCount(diCount,doCount,aiCount,aoCount);
        isInitialedOk=true;
        return 1;

    }
    return -2;
}

int ModbusIoModuleDriver::getModbusMaster(modbus_t* modbusMasterReturn)
{
    if(NULL==modbusMaster)
    {
        modbusMasterReturn=NULL;
        return -1;
    }
    else
    {
        modbusMasterReturn=modbusMaster;
    }
    return 1;
}


//int ModbusIoModuleDriver::setModbusMaster(modbus_t* modbusMasterIn)
//{
//    modbusMaster=modbusMasterIn;
//    modbus_set_slave(modbusMaster,modbusId);
//    return 1;
//}

bool ModbusIoModuleDriver::isInitialOkStatus()
{
    return isInitialedOk;
}

int ModbusIoModuleDriver::getDiDoCount(int &diCounter,int &doCounter,int &aiCounter, int &aoCounter)
{

    if(false==isInitialedOk)
    {
        return -1;
    }
    diCounter=diCount;
    doCounter=doCount;
    aiCounter=aiCount;
    aoCounter=aoCount;

    return 1;
}


int ModbusIoModuleDriver::connectPort()
{


    if(E_MODBUS_TYPE_TCP==comParameter.modbusType)
    {
        modbusMaster = modbus_new_tcp(comParameter.ip.toStdString().data()
                                      ,comParameter.port);//由于是tcp client 连接，在同一程序中相同的端口可以连接多次
        modbus_set_slave(modbusMaster,modbusId);
        if (modbus_connect(modbusMaster) == -1)
        {
            qDebug()<<"ModbusIoModuleDriver::connectPort connect failed";
            modbus_free(modbusMaster);
            modbusMaster=NULL;
            return -2;
        }
        else
        {
            modbus_set_response_timeout(modbusMaster, 0, 500000);
//            qDebug()<<"connect success";
            return 1;
        }
    }
    else if(E_MODBUS_TYPE_RTU==comParameter.modbusType)
    {

        modbusMaster =modbus_new_rtu(comParameter.serialDeviceName.toStdString().data(),
                                     comParameter.baud, (*comParameter.parity.toStdString().data()),
                                            comParameter.data_bit, comParameter.stop_bit);
        modbus_set_slave(modbusMaster,modbusId);
        if (modbus_connect(modbusMaster) == -1)
        {
            qDebug()<<"ModbusIoModuleDriver::connectPort connect failed";
            modbus_free(modbusMaster);
            modbusMaster=NULL;
            return -2;
        }
        else
        {
            modbus_set_response_timeout(modbusMaster, 0, 500000);
//            qDebug()<<"connect success";
            return 1;
        }
    }
}

int ModbusIoModuleDriver::readAllDi(QVector<bool> & diReturn)
{
    if( false==isInitialedOk || diReturn.size()>diCount)
    {
        diReturn.resize(0);
        return -1;
    }

    diReturn.resize(diCount);
    return readDi(diReturn);
}


int ModbusIoModuleDriver::readDi(QVector<bool> & diReturn)
{

    if( false==isInitialedOk || diReturn.size()>diCount)
    {
        return -1;
    }
    if(1!=checkModbusMaster())
    {
        return -100;
    }

    uint8_t dataStream[diReturn.size()];
    uint16_t data16List[4];

    switch(vendorId)
    {
        case E_VENDOR_ID_NAI_LI_KE:
        {
            int resultKey=modbus_read_registers(modbusMaster,0x8040,2,data16List);
            if(-1!=resultKey)
            {
    //                qDebug()<<"readDi:modbus_read_registers sucess"<<resultKey;
                for(int i=0;i<diReturn.size();i++)
                {
                   diReturn[i]= data16List[1]&1;
                   data16List[1]=data16List[1]>>1;
                }
//                qDebug()<<diReturn;
                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
        case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
        {
            int resultKey=modbus_read_input_bits(modbusMaster
                                                ,regAdd.diStartAdd,diReturn.size(),dataStream);
            if(-1!=resultKey)
            {
//                qDebug()<<"readDi:modbus_read_input_bits sucess"<<resultKey;
                for(int i=0;i<diReturn.size();i++)
                {
                   diReturn[i]= dataStream[i];
                }
                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
    }

    return -1;
}

int ModbusIoModuleDriver::readDi( int diIndex, bool & diReturn)
{


    if( false==isInitialedOk)
    {
        return -1;
    }
    if(1!=checkModbusMaster())
    {
        return -100;
    }

    uint8_t dataStream[1];

    switch(vendorId)
    {
        case E_VENDOR_ID_NAI_LI_KE:
        {
            return -1;
            break;
        }
        case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
        {
            int resultKey=modbus_read_input_bits(modbusMaster
                                                ,regAdd.diStartAdd+diIndex,1,dataStream);
            if(-1!=resultKey)
            {
//                qDebug()<<"readDi:modbus_read_input_bits sucess"<<resultKey;

                   diReturn= dataStream[0];

                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
    }

    return -1;
}

int ModbusIoModuleDriver::readDo(QVector<bool> & doReturn)
{

    if( false==isInitialedOk|| doReturn.size()>doCount)
    {
        return -1;
    }
    if(1!=checkModbusMaster())
    {
        return -100;
    }

    uint8_t dataStream[doReturn.size()];

    switch(vendorId)
    {

        case E_VENDOR_ID_NAI_LI_KE:
        {
            return -1;
        }
        case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
        {
            int resultKey=modbus_read_bits(modbusMaster
                                                ,regAdd.doStartAdd,doReturn.size(),dataStream);
            if(-1!=resultKey)
            {
//                qDebug()<<"readDo:modbus_read_bits sucess"<<resultKey;
                for(int i=0;i<doReturn.size();i++)
                {
                   doReturn[i]= dataStream[i];
                }
                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
    }

    return -1;
}

int ModbusIoModuleDriver::readDo(int doIndex, bool & doReturn)
{

    if( false==isInitialedOk)
    {
        return -1;
    }
    if(1!=checkModbusMaster())
    {
        return -100;
    }

    uint8_t dataStream[1];

    switch(vendorId)
    {
        case E_VENDOR_ID_NAI_LI_KE:
        {
            return -1;
        }
        case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
        {
            int resultKey=modbus_read_bits(modbusMaster
                                                ,regAdd.doStartAdd+doIndex,1,dataStream);
            if(-1!=resultKey)
            {
//                qDebug()<<"readDo:modbus_read_bits sucess"<<resultKey;

                   doReturn= dataStream[0];
                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
    }

    return -1;
}

int ModbusIoModuleDriver::writeDo(QVector<bool> doValue)
{

    if( false==isInitialedOk|| doValue.size()>doCount)
    {
        return -1;
    }
    if(1!=checkModbusMaster())
    {
        return -100;
    }

    uint8_t dataStream[doValue.size()];
    for(int i=0;i<doValue.size();i++)
    {
       dataStream[i]=doValue[i];
    }

    switch(vendorId)
    {
        case E_VENDOR_ID_NAI_LI_KE:
        {
            uint16_t writeData[2];
            for(int i=0;i<doValue.size();i++)
            {
               if(i<16)
               {
                   if(i<8)
                   {
                        writeData[0]=writeData[0]|doValue[7-i];
                   }
                   else
                   {
                       writeData[0]=writeData[0]|doValue[23-i];
                   }
                   if(15!=i)
                   {
                       writeData[0]=writeData[0]<<1;
                   }

               }
               else
               {
                   return -1;
               }
            }
            int resultKey=modbus_write_registers(modbusMaster,0x8050,2,writeData);
            if(-1!=resultKey)
            {
    //                qDebug()<<"writeDo:modbus_write_bits sucess"<<resultKey;

                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
        case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
        {
            int resultKey=modbus_write_bits(modbusMaster
                                                ,regAdd.doStartAdd,doValue.size(),dataStream);
            if(-1!=resultKey)
            {
//                qDebug()<<"writeDo:modbus_write_bits sucess"<<resultKey;

                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
    }

    return -1;
}

int ModbusIoModuleDriver::writeDo(int doIndex, bool doValue)
{

    if( false==isInitialedOk)
    {
        return -1;
    }
    if(1!=checkModbusMaster())
    {
        return -100;
    }

    uint8_t dataStream[1];

    dataStream[0]=doValue;


    switch(vendorId)
    {
        case E_VENDOR_ID_NAI_LI_KE:
        {
            uint16_t writeData;
            if(true==doValue)
            {
                writeData=0xff00;
            }
            else
            {
                writeData=0;
            }
            int resultKey=modbus_write_register(modbusMaster
                                                ,doIndex,writeData);
            if(-1!=resultKey)
            {
    //                qDebug()<<"writeDo:modbus_write_bits sucess"<<resultKey;

                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
        case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
        {
            int resultKey=modbus_write_bits(modbusMaster
                                                ,regAdd.doStartAdd+doIndex,1,dataStream);
            if(-1!=resultKey)
            {
//                qDebug()<<"writeDo:modbus_write_bits sucess"<<resultKey;

                return 1;
            }
            else
            {
                return -1;
            }

            break;
        }
    }

    return -1;
}



int ModbusIoModuleDriver::checkModbusMaster()
{
    if(E_MODBUS_TYPE_TCP==comParameter.modbusType)
    {
        return 1;
    }
    if(NULL==globalCurrentModbusMaster && -1==*globalCurrentAlias)
    {
        int returnKey;
        returnKey=connectPort();
        if(1==returnKey)
        {
            *globalCurrentAlias=modbusId;
            globalCurrentModbusMaster=modbusMaster;
            return 1;
        }
        else
        {
            return -1;
        }
    }
    else if(modbusId !=*globalCurrentAlias)
    {
        int returnKey;
        modbus_free(globalCurrentModbusMaster);
        returnKey=connectPort();
        if(1==returnKey)
        {
            *globalCurrentAlias=modbusId;
            globalCurrentModbusMaster=modbusMaster;
            return 1;
        }
        else
        {
            return -2;
        }
    }

    return 1;
}
